package com.guodi.map.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.guodi.common.constant.StatusCode;
import com.guodi.common.utils.PageData;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.core.tool.api.R;
import com.guodi.map.dto.MapDivisionTOLayerDto;
import com.guodi.map.entity.MapDivision;
import com.guodi.map.entity.MapLayer;
import com.guodi.map.entity.MapLayerField;
import com.guodi.map.service.IMapDivisionService;
import com.guodi.map.service.IMapLayerFieldService;
import com.guodi.map.service.IMapLayerService;
import com.guodi.map.utils.RecursionUtil;
import com.guodi.map.utils.VerificationUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @描述：行政区划管理控制类
 * @作者: 代鹏刚
 * @日期: 2020-04-07
 */
@RestController
@RequestMapping("/MapDivision")
@Api(value = "API - MapDivisionController", tags = "行政区划管理控制类")
public class MapDivisionController extends BaseController {

    @Autowired
    public IMapDivisionService mapDivisionService;
    @Autowired
    private IMapLayerService mapLayerService;
    @Autowired
    private IMapLayerFieldService mapLayerFieldService;

    /**
    * @描述: 根据实体属性分页查询
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020-04-07
    **/
    @PostMapping("/listByEntity")
    @ApiOperation(value = " 根据实体属性分页查询")
    public R listByEntity(MapDivision mapDivision){
        List<MapDivision> mapDivisions = mapDivisionService.listByEntity(mapDivision);
        return R.data(mapDivisions);
    }

    /**
     * @描述: 根据主键查询
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-04-07
     **/
    @PostMapping("/findById")
    @ApiOperation(value = "根据主键查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", required = true,
                    dataType = "string", paramType = "query")
    })
    public R findById(String id) {
        if(StringUtils.isBlank(id)){
            return R.fail(StatusCode.ERROR_CODE_40005,"id不能为空");
        }
        MapDivision mapDivision = mapDivisionService.getById(id);
        MapLayer byId = mapLayerService.getById(mapDivision.getLayerId());
        if(byId!=null){
            mapDivision.setLayerUrl(byId.getLayerUrl()+"/"+byId.getLayerTable());
        }
        return R.data(mapDivision);
    }

    /**
     * @描述: 新增
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-04-07
     **/
    @PostMapping("/save")
    @ApiOperation(value = "新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "layerId", value = "图层ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "codeField", value = "行政区划代码字段", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "name", value = "名称", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "parentCode", value = "上级编码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "extend", value = "图形范围", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "string", paramType = "query")
    })
    public R save(MapDivision mapDivision){
        //判断当前目录下，目录名称是否存在
        Collection collection = mapDivisionService.listByMap(VerificationUtil.verifyMapByCode(mapDivision.getCode(),null));
        if(collection.size() > 0){
            return R.fail(StatusCode.ERROR_CODE_40005,"该编码已经存在,请更换！");
        }
        prepareData(mapDivision, true);
        mapDivision.setId(UuidUtil.get32UUID());
        mapDivisionService.save(mapDivision);
        return R.data(mapDivision);
    }

    /**
     * @描述: 修改
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-04-07
     **/
    @PostMapping("/update")
    @ApiOperation(value = "修改")
    public R update(MapDivision mapDivision) {
        if(StringUtils.isNotBlank(mapDivision.getCode())){
            //验证修改的code唯一
            List<MapDivision> list = (List<MapDivision>)mapDivisionService.listByMap(VerificationUtil.verifyMapByCode(mapDivision.getCode(),null));
            if(list.size() > 0 && !list.get(0).getId().equals(mapDivision.getId())){
                return R.fail(StatusCode.ERROR_CODE_40005,"该编码已经存在,请更换！");
            }
        }
        prepareData(mapDivision, false);
        mapDivisionService.updateById(mapDivision);
        return R.data(mapDivision);
    }

    /**
     * @描述: 根据主键删除
     * @入参: id
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-04-07
     **/
    @PostMapping("/delete")
    @ApiOperation(value = "根据主键删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", required = true,
                    dataType = "string", paramType = "query")
    })
    public R delete(String id){
        MapDivision byId = mapDivisionService.getById(id);
        //获取行政区划树
        List<String> rootIds = new ArrayList<>();
        rootIds.add(byId.getId());
        List<MapDivision> mapDivisions = mapDivisionService.listDivisionTreeData(rootIds);
        if(mapDivisions!=null && !mapDivisions.isEmpty()){
            List<String> ids = mapDivisions.stream().map(MapDivision::getId).collect(Collectors.toList());
            mapDivisionService.removeByIds(ids);
        }
        //删除本身
        mapDivisionService.removeById(id);
        return R.status(true);
    }

    /**
    * @描述: 获取行政区划代码目录树
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/4/7 17:22
    **/
    @PostMapping("/listDivisionTree")
    @ApiOperation(value = "获取行政区划代码目录树")
    public R listDivisionTree(){
        //获取行政区划树
        List<MapDivision> treeList = mapDivisionService.listDivisionTree();
        return R.data(treeList);
    }

    /**
    * @描述:获取行政区划代码目录树数据(数据，非父子节点类型)
    * @入参:
    * @出参:
    * @作者: 郑文彬
    * @日期: 2020/4/10 16:21
    **/
    @PostMapping("/listDivisionTreeData")
    @ApiOperation(value = "获取行政区划代码目录树数据")
    public R listDivisionTreeData(){
        //获取行政区划树
        List<String> rootIds = new ArrayList<>();
        List<MapDivision> list = mapDivisionService.list();
        for (MapDivision mapDivision: list) {
            boolean isRoot = true;
            for (MapDivision mapDivision2: list) {
                if(mapDivision.getParentCode().equals(mapDivision2.getCode())){
                    isRoot = false;
                }
            }
            if(isRoot){
                rootIds.add(mapDivision.getId());
            }
        }
        List<MapDivision> treeList = mapDivisionService.listDivisionTreeData(rootIds);
        //2020-0509兼容pgSQL
        if (treeList != null && treeList.size() > 0) {
            boolean isTrue = treeList.stream().filter(m -> m.getLevel() == 0).findAny().isPresent();
            if(isTrue){
                List<MapDivision> resultList = new ArrayList<>();
                sortList(treeList,"-1",resultList);
                return R.data(resultList);
            }else {
                return R.data(treeList);
            }
        } else {
            return R.data(null);
        }
    }

    public static void sortList(List<MapDivision> list, String id, List<MapDivision> resultList) {
        // 按行政区排序
        List<MapDivision> collect = list.stream().sorted(Comparator.comparing(MapDivision::getCode)).collect(Collectors.toList());
        for (MapDivision node :collect) {
            if (node.getParentId().equals(id)) {
                node.setLevel(node.getLevel()+1);
                resultList.add(node);
                sortList(list,node.getId(),resultList);
            }
        }
    }
    /**
    * @描述: 根据图层地址获取图层字段、字段值、名称
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/4/8 14:41
    **/
    @PostMapping(value="/getLayerInfoByLayerId")
    @ApiOperation(value = "获取行政区划代码目录树")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "layerId", value = "图层ID", required = true, dataType = "string", paramType = "query")
    })
    public R getLayerInfoByLayerId(String layerId){
        //返回结果集
        Map resultJson = new HashMap();
        //根据图层ID获取图层对象
        MapLayer mapLayer = mapLayerService.getById(layerId);
        //根据图层ID获取字段集合
        List<MapLayerField> fieldAllList = mapLayerFieldService.listByLayerId(layerId);
        //存储前端显示字段集合
        List<MapLayerField> fieldList = new ArrayList<>();
        for(MapLayerField mapLayerField : fieldAllList){
            if(mapLayerField.getFieldName().contains("shape")){
                continue;
            }
            fieldList.add(mapLayerField);
        }
        resultJson.put("layerFiledArray", fieldList);
        resultJson.put("layerName", mapLayer.getName());
        return R.data(resultJson);
    }

    /**
    * @描述: 导入行政区划
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/4/8 16:13
    **/
    @PostMapping(value="/importLayer")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "one_layer_url", value = "第一个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_layer_id", value = "第一个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_layer_name", value = "第一个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_field_code", value = "第一个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_field_name", value = "第一个行政区划名称字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_layer_url", value = "第二个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_layer_id", value = "第二个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_layer_name", value = "第二个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_field_code", value = "第二个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_field_name", value = "第二个行政区划名称字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_layer_url", value = "第三个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_layer_id", value = "第三个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_layer_name", value = "第三个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_field_code", value = "第三个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_field_name", value = "第三个行政区划名称字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_layer_url", value = "第四个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_layer_id", value = "第四个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_layer_name", value = "第四个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_field_code", value = "第四个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_field_name", value = "第四个行政区划名称字段名",  dataType = "string", paramType = "query"),
    })
    @ApiOperation(value = "导入行政区划")
    public R importLayer(){
        HttpServletRequest request = this.getRequest();
        PageData pageData = new PageData(request);
        mapDivisionService.importLayer(pageData);
        return R.data(null);
    }

    /**
     * @描述: SuperMap图层服务导入行政区划
     * @入参:
     * @出参:
     * @作者: 戴伙进
     * @日期: 2020/05/08 16:13
     **/
    @PostMapping(value="/importSuLayer")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "one_layer_url", value = "第一个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_layer_id", value = "第一个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_layer_name", value = "第一个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_field_code", value = "第一个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "one_field_name", value = "第一个行政区划名称字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_layer_url", value = "第二个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_layer_id", value = "第二个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_layer_name", value = "第二个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_field_code", value = "第二个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "two_field_name", value = "第二个行政区划名称字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_layer_url", value = "第三个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_layer_id", value = "第三个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_layer_name", value = "第三个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_field_code", value = "第三个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "three_field_name", value = "第三个行政区划名称字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_layer_url", value = "第四个图层url",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_layer_id", value = "第四个图层id",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_layer_name", value = "第四个图层名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_field_code", value = "第四个行政区划代码字段名",  dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "four_field_name", value = "第四个行政区划名称字段名",  dataType = "string", paramType = "query"),
    })
    @ApiOperation(value = "SuperMap图层导入行政区划")
    public R importSuLayer(MapDivisionTOLayerDto dto){
        mapDivisionService.importSuLayer(dto);
        return R.data(null);
    }

    /**
    * @描述: 根据行政区划代码code查询
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/4/15 15:43
    **/
    @PostMapping(value="/findByCode")
    @ApiOperation(value = "根据行政区划代码code查询")
    @ApiImplicitParam(name = "code", value = "行政区划编码", required = true, dataType = "string", paramType = "query")
    public R findByCode(String code){
        LambdaQueryWrapper<MapDivision> queryWrapper = (new QueryWrapper()).lambda();
        queryWrapper.eq(MapDivision::getCode, code);
        MapDivision mapDivision = mapDivisionService.getOne(queryWrapper);
        return R.data(mapDivision);
    }

    /**
    * @描述: 根据当前用户关联行政区划匹配系统行政区划代码
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2021/1/14 15:34
    **/
    @PostMapping(value="/mateByCode")
    @ApiOperation(value = "根据当前用户关联行政区划匹配系统行政区划代码")
    @ApiImplicitParam(name = "code", value = "行政区划编码", required = true, dataType = "string", paramType = "query")
    public R mateByCode(String code){
        MapDivision mapDivision = mapDivisionService.mateByCode(code.replaceAll("0+$",""));
        if(null == mapDivision){
            return R.fail(StatusCode.ERROR_CODE_40005,"请在GIS运维行政区划管理配置当前用户机构关联的行政区划！");
        }
        return R.data(mapDivision);
    }

    /**
    * @描述: 获取行政区划编码获取行政区划树
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/6/11 16:29
    **/
    @PostMapping("/listDataByCode")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "行政区划代码",required = true, dataType = "string", paramType = "query")
    })
    @ApiOperation(value = "获取行政区划编码获取行政区划树")
    public R listDataByCode(String code){
        if(null == code){
            return R.fail(StatusCode.ERROR_CODE_40005,"请在GIS运维行政区划管理配置当前用户机构关联的行政区划！");
        }
        List<MapDivision> mapDivisionList = mapDivisionService.listDataByCode(code);
        if(null != mapDivisionList && mapDivisionList.size() > 0){
            List<MapDivision> collect = mapDivisionList.stream().sorted(Comparator.comparing(MapDivision::getCode)).collect(Collectors.toList());
            List<MapDivision> mapDivisions = RecursionUtil.buildMapDivision(collect, collect.get(0).getParentCode());
            for (MapDivision mapDivision : mapDivisions) {
                if(mapDivision.getChildren()==null||mapDivision.getChildren().isEmpty()){
                    mapDivision.setChildren(null);
                }
            }
            return R.data(mapDivisions);
        }else {
            return R.data(null);
        }
    }

    private void prepareData(MapDivision mapDivision, boolean isSave) {
        if(isSave){
            mapDivision.setCreator(getUser().getUserId().toString());
            mapDivision.setCreateTime(new Date());
            //防止误修改
            mapDivision.setModifier(null);
            mapDivision.setModifyTime(null);
        }else{
            mapDivision.setModifier(getUser().getUserId().toString());
            mapDivision.setModifyTime(new Date());
            //防止误修改
            mapDivision.setCreator(null);
            mapDivision.setCreateTime(null);
        }
    }
}
